﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Enyim.Caching;
using Enyim.Caching.Memcached; 
namespace ShiNiu.Memcahce
{
  
        /// <summary>
        /// MemcahceCache
        /// </summary>
        public class MemcahceCache
        {

            private static Lazy<MemcachedClient> _memcache = new Lazy<MemcachedClient>(
                    () =>
                    {
                        return new MemcachedClient();
                    });

            /// <summary>
            /// 客户端
            /// </summary>
            public   MemcachedClient MC
            {
                get
                {
                    return _memcache.Value;
                }
            }


        public static MemcahceCache GetCache()
        {
            return new MemcahceCache();
        }

        public MemcahceCache()
            {
            }

            private bool IsObjectType(Type type)
            {
                return type.IsClass || type.IsInterface;
            }

            /// <summary>
            ///  
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="cacheKey"></param>
            /// <returns></returns>
            public T Get<T>(string cacheKey)
            {
                if (IsObjectType(typeof(T)))
                    return MC.Get<string>(cacheKey).Deserialize<T>();

                return MC.Get<T>(cacheKey);
            }

            public object Get(string cacheKey)
            {
                return MC.Get(cacheKey);
            }

            /// <summary>
            /// 写入Memcache，无过期时间
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="cacheKey"></param>
            /// <param name="value"></param>
            /// <remarks>Class 和 Interface类型会转换成JSON</remarks>
            /// <returns></returns>
            public bool Write<T>(string cacheKey, T value)
            {
                if (IsObjectType(typeof(T)))
                {
                    var str = value.ToJson();
                    MC.Store(StoreMode.Set, cacheKey, str);
                }
                return MC.Store(StoreMode.Set, cacheKey, value);
            }

            /// <summary>
            /// 写入Memcache，有过期时间
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="cacheKey"></param>
            /// <param name="value"></param>
            /// <param name="expireTime"></param>
            /// <remarks>Class 和 Interface类型会转换成JSON</remarks>
            /// <returns></returns>
            public bool Write<T>(string cacheKey, T value, TimeSpan expireTime)
            {
                if (IsObjectType(typeof(T)))
                {
                    var str = value.ToJson();
                    MC.Store(StoreMode.Set, cacheKey, str, expireTime);
                }
                return MC.Store(StoreMode.Set, cacheKey, value, expireTime);
            }

            public bool Remove(string cacheKey)
            {
                return MC.Remove(cacheKey);
            }

            /// <summary>
            /// 清空缓存
            /// </summary>
            public virtual void FlushCache()
            {
                MC.FlushAll();
            }

            /// <summary>
            /// 是否存在该缓存
            /// </summary>
            /// <param name="key">键</param>
            /// <returns></returns>
            public virtual bool IsExists(string key)
            {
                return MC.Get(key) != null;
            }

            /// Created By :xiao
            /// Created Date：2018-07-20
            /// Modify By: 
            /// Modify Date:
            /// Modify Reason:
            /// <summary>
            /// 设置缓存
            /// </summary> 
            /// <param name="key">缓存Key</param> 
            /// <param name="setFunc">缓存</param> 
            /// <author>xiao</author>
            /// <remarks></remarks>
            /// <returns></returns>
            public T GetOrAdd<T>(string key, Func<string, T> setFunc) where T : class
            {
                object obj;
                if (MC.TryGet(key, out obj))
                {
                    return Get<T>(key);       
                }
                else
                {
                    MC.Remove(key);
                    obj = setFunc(key);

                    MC.Store(StoreMode.Set, key, obj.ToJson());
                    return obj as T;
                }
            }
        }
    }
 
